{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import timeit"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "listcomp        : 0.117 0.113 0.120\n",
      "listcomp + func : 0.172 0.168 0.172\n",
      "filter + lambda : 0.150 0.150 0.143\n",
      "filter + func   : 0.143 0.150 0.144\n"
     ]
    }
   ],
   "source": [
    "TIMES = 100000\n",
    "\n",
    "SETUP = \"\"\"\n",
    "symbols = '$¢£¥€¤'\n",
    "def non_ascii(c):\n",
    "    return c > 127\n",
    "\"\"\"\n",
    "\n",
    "def clock(label, cmd):\n",
    "    res = timeit.repeat(cmd, setup=SETUP, number=TIMES)\n",
    "    print(label, *('{:.3f}'.format(x) for x in res))\n",
    "\n",
    "clock('listcomp        :', '[ord(s) for s in symbols if ord(s) > 127]')\n",
    "clock('listcomp + func :', '[ord(s) for s in symbols if non_ascii(ord(s))]')\n",
    "clock('filter + lambda :', 'list(filter(lambda c: c > 127, map(ord, symbols)))')\n",
    "clock('filter + func   :', 'list(filter(non_ascii, map(ord, symbols)))')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 2-9 具名元组"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "City(name='Tokyo', country='JP', population=36.933, coordinates=(35.689722, 139.691667))"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from collections import namedtuple\n",
    "# City = namedtuple('City', ['name', 'country', 'population', 'coordinates'])\n",
    "City = namedtuple('City', 'name country population coordinates')\n",
    "tokyo = City('Tokyo', 'JP', 36.933, (35.689722, 139.691667))\n",
    "tokyo"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "('name', 'country', 'population', 'coordinates')"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "City._fields"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "City(name='Delhi NCR', country='IN', population=21.935, coordinates=LatLong(lat=28.613889, long=77.208889))"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "LatLong = namedtuple('LatLong', 'lat long')\n",
    "delhi_data = ('Delhi NCR', 'IN', 21.935, LatLong(28.613889, 77.208889))\n",
    "# delhi = City(*delhi_data)\n",
    "delhi = City._make(delhi_data)\n",
    "delhi"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "OrderedDict([('name', 'Delhi NCR'),\n",
       "             ('country', 'IN'),\n",
       "             ('population', 21.935),\n",
       "             ('coordinates', LatLong(lat=28.613889, long=77.208889))])"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "delhi._asdict()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 切片"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [],
   "source": [
    "invoice = \"\"\"\n",
    "0.....6................................40........52...55........\n",
    "1909  Pimoroni PiBrella                    $17.50    3    $52.50\n",
    "1489  6mm Tactile Switch x20                $4.95    2     $9.90\n",
    "1510  Panavise Jr. - PV-201                $28.00    1    $28.00\n",
    "1601  PiTFT Mini Kit 320x240               $34.95    1    $34.95\n",
    "\"\"\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "   $17.50    Pimoroni PiBrella                 \n",
      "    $4.95    6mm Tactile Switch x20            \n",
      "   $28.00    Panavise Jr. - PV-201             \n",
      "   $34.95    PiTFT Mini Kit 320x240            \n",
      " \n"
     ]
    }
   ],
   "source": [
    "SKU = slice(0, 6)\n",
    "DESCRIPTION = slice(6, 40)\n",
    "UNIT_PRICE = slice(40, 52)\n",
    "QUANTITY = slice(52, 55)\n",
    "ITEM_TOTAL = slice(55, None)\n",
    "line_items = invoice.split('\\n')[2:]\n",
    "for item in line_items:\n",
    "    print(item[UNIT_PRICE], item[DESCRIPTION])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## bisect"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [],
   "source": [
    "import bisect\n",
    "import sys"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [],
   "source": [
    "HAYSTACK = [1, 4, 5, 6, 8, 12, 15, 20, 21, 23, 23, 26, 29, 30]\n",
    "NEEDLES = [0, 1, 2, 5, 8, 10, 22, 23, 29, 30, 31]\n",
    "\n",
    "ROW_FMT = '{0:2d} @ {1:2d}    {2}{0:<2d}'"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "DEMO: bisect\n",
      "haystack ->  1  4  5  6  8 12 15 20 21 23 23 26 29 30\n",
      "31 @ 14      |  |  |  |  |  |  |  |  |  |  |  |  |  |31\n",
      "30 @ 14      |  |  |  |  |  |  |  |  |  |  |  |  |  |30\n",
      "29 @ 13      |  |  |  |  |  |  |  |  |  |  |  |  |29\n",
      "23 @ 11      |  |  |  |  |  |  |  |  |  |  |23\n",
      "22 @  9      |  |  |  |  |  |  |  |  |22\n",
      "10 @  5      |  |  |  |  |10\n",
      " 8 @  5      |  |  |  |  |8 \n",
      " 5 @  3      |  |  |5 \n",
      " 2 @  1      |2 \n",
      " 1 @  1      |1 \n",
      " 0 @  0    0 \n"
     ]
    }
   ],
   "source": [
    "def demo(bisect_fn):\n",
    "    for needle in reversed(NEEDLES):\n",
    "        position = bisect_fn(HAYSTACK, needle)\n",
    "        offset = '  |' * position\n",
    "        print(ROW_FMT.format(needle, position, offset))\n",
    "        \n",
    "if __name__ == '__main__':\n",
    "    if sys.argv[-1] == 'left':\n",
    "        bisect_fn = bisect.bisect_left\n",
    "    else:\n",
    "        bisect_fn = bisect.bisect\n",
    "    print('DEMO:', bisect_fn.__name__)\n",
    "    print('haystack ->', ' '.join('%2d' % n for n in HAYSTACK))\n",
    "    demo(bisect_fn)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['F', 'A', 'C', 'C', 'B', 'A', 'A']"
      ]
     },
     "execution_count": 29,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "def grade(score, breakpoints=[60, 70, 80, 90], grades='FDCBA'):\n",
    "    i = bisect.bisect(breakpoints, score)\n",
    "    return grades[i]\n",
    "\n",
    "[grade(score) for score in [33, 99, 77, 70, 89, 90, 100]]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      " 4 -> [4]\n",
      "11 -> [4, 11]\n",
      " 5 -> [4, 5, 11]\n",
      " 1 -> [1, 4, 5, 11]\n",
      " 8 -> [1, 4, 5, 8, 11]\n",
      " 6 -> [1, 4, 5, 6, 8, 11]\n",
      " 3 -> [1, 3, 4, 5, 6, 8, 11]\n"
     ]
    }
   ],
   "source": [
    "import random\n",
    "\n",
    "SIZE = 7\n",
    "random.seed(1924)\n",
    "my_list = []\n",
    "\n",
    "for i in range(SIZE):\n",
    "    new_item = random.randrange(SIZE*2)\n",
    "    bisect.insort(my_list, new_item)\n",
    "    print('%2d ->' % new_item, my_list)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 2.9　当列表不是首选时"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "metadata": {},
   "outputs": [],
   "source": [
    "from array import array\n",
    "from random import random\n",
    "\n",
    "floats = array('d', (random() for i in range(10**7)))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 42,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0.22831568237378608"
      ]
     },
     "execution_count": 42,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "floats[-1]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 45,
   "metadata": {},
   "outputs": [],
   "source": [
    "fp = open('floats.bin', 'wb')\n",
    "floats.tofile(fp)\n",
    "fp.close()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 47,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0.22831568237378608"
      ]
     },
     "execution_count": 47,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "floats2 = array('d')\n",
    "fp = open('floats.bin', 'rb')\n",
    "floats2.fromfile(fp, 10**7)\n",
    "fp.close()\n",
    "floats2[-1]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 49,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 49,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "floats == floats2"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 双向队列"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "from collections import deque"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "deque([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "dq = deque(range(10), maxlen=10)\n",
    "dq"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "deque([7, 8, 9, 0, 1, 2, 3, 4, 5, 6])"
      ]
     },
     "execution_count": 15,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "dq.rotate(3)\n",
    "dq"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "deque([1, 2, 3, 4, 5, 6, 7, 8, 9, 0])"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "dq.rotate(-4)\n",
    "dq"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "deque([-1, 1, 2, 3, 4, 5, 6, 7, 8, 9])"
      ]
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "dq.appendleft(-1)\n",
    "dq"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "deque([3, 4, 5, 6, 7, 8, 9, 11, 22, 33])"
      ]
     },
     "execution_count": 18,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "dq.extend([11, 22, 33])\n",
    "dq"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "deque([40, 30, 20, 10, 3, 4, 5, 6, 7, 8])"
      ]
     },
     "execution_count": 19,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "dq.extendleft([10, 20, 30, 40])\n",
    "dq"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    " "
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
